<?php

namespace api\modules\v1\forms\infusion;

use common\helpers\DateHelper;
use common\models\base\DrugConfig;
use common\models\member\Attr;
use common\models\member\Member;
use common\models\patient\DrugSurplus;
use common\models\patient\InfusionQueue;
use common\models\patient\InfusionQueueDrug;
use common\models\patient\User;
use common\models\rbac\Department;
use Yii;
use yii\base\Model;

/**
 * Class QueueForm
 * @package api\modules\v1\forms\infusion
 */
class QueueForm extends Model
{
    // 队列ID
    public $id;
    // 项目ID
    public $project_id;
    // 患者ID
    public $patient_user_id;
    // 患者药品IDs
    public $surplus_drug_id;
    // 排队类型【1静滴、2肌注】
    public $type;
    // 操作人ID
    public $operate_id;

    // 患者信息
    protected $_patientInfo;
    // 患者药品列表
    protected $_patientDrugSurplusList;
    // 队列信息
    protected $_queueInfo;
    // 原队列信息
    protected $_oldQueueInfo;
    // 最大排号
    protected $_maxOrderNum;
    // 队列患者药品列表
    protected $_queueDrugSurplusList;



    public function rules()
    {
        return [
            // 参数验证
            [['project_id', 'patient_user_id', 'surplus_drug_id', 'type'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['project_id', 'id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['call']],
            [['project_id', 'id', 'operate_id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['infusion']],
            [['project_id', 'id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['cancel']],


            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['call', 'infusion', 'cancel']],
//            [['project_id'], 'checkProjectId', 'skipOnEmpty' => false, 'on' => ['create']],
            [['patient_user_id'], 'checkPatientUserId', 'skipOnEmpty' => false, 'on' => ['create']],
            [['type'], 'checkType', 'skipOnEmpty' => false, 'on' => ['create']],
            [['surplus_drug_id'], 'checkSurplusDrugId', 'skipOnEmpty' => false, 'on' => ['create']],
            [['operate_id'], 'checkOperateId', 'skipOnEmpty' => false, 'on' => ['infusion']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 排队
        $scenarios['create'] = ['project_id', 'patient_user_id', 'surplus_drug_id', 'type'];
        // 呼叫
        $scenarios['call'] = ['project_id', 'id'];
        // 输液
        $scenarios['infusion'] = ['project_id', 'id', 'operate_id'];
        // 撤销
        $scenarios['cancel'] = ['project_id', 'id'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'project_id' => '项目',
            'patient_user_id' => '患者ID',
            'surplus_drug_id' => '患者药品ID',
            'type' => '排队类型',
            'operate_id' => '操作人',
        ];
    }

    /**
     * 检验队列ID
     *
     * @param $attribute
     * @return bool
     */
    public function checkId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $queue = $this->getQueueInfo();
        if (empty($queue)) {
            $this->addError($attribute, '队列不存在');
            return true;
        }
        if ($this->getScenario() == 'call') {// 叫号
            if ($queue->status != InfusionQueue::STATUS_WAIT) {
                $this->addError($attribute, '队列状态异常');
                return true;
            }
        } elseif ($this->getScenario() == 'cancel') {// 撤销
            if ($queue->status == InfusionQueue::STATUS_CANCEL) {
                $this->addError($attribute, '队列已撤销，请勿重复操作');
                return true;
            }
        }else {// 输液
            if (!in_array($queue->status, [InfusionQueue::STATUS_WAIT, InfusionQueue::STATUS_CALLING])) {
                $this->addError($attribute, '请勿重复提交');
                return true;
            }
        }
        if ($queue->project_id != $this->project_id) {
            $this->addError($attribute, '非当前项目队列');
            return true;
        }
        $today = DateHelper::today();
        if ($queue->created_at < $today['start']) {
            $this->addError($attribute, '非当天叫号，无法操作');
            return true;
        }
        $this->patient_user_id = $queue->patient_user_id;
    }

    /**
     * 检验项目ID
     * @param $attribute
     * @return bool
     */
    /*public function checkProjectId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }
    }*/

    /**
     * 检验患者ID
     * @param $attribute
     * @return bool
     */
    public function checkPatientUserId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $patient = $this->getPatientInfo();
        if (empty($patient)) {
            $this->addError($attribute, '患者不存在');
            return true;
        }
        if ($patient->status != User::STATUS_ENABLE) {
            $this->addError($attribute, '患者状态异常');
            return true;
        }
        if ($patient->project_id != $this->project_id) {
            $this->addError($attribute, '患者非当前项目');
            return true;
        }
        // 未完成队列
        $oldQueueInfo = $this->getOldQueueInfo();
        if ($oldQueueInfo && ($oldQueueInfo->status == InfusionQueue::STATUS_WAIT || $oldQueueInfo->call_time >= Yii::$app->params['time'] - InfusionQueue::WAIT_TIME)) {
            $this->addError($attribute, '患者存在排队信息');
            return true;
        }
    }

    /**
     * 检验排队类型
     * @param $attribute
     * @return bool
     */
    public function checkType($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (!in_array($this->type, [InfusionQueue::TYPE_JD, InfusionQueue::TYPE_JZ])) {
            $this->addError($attribute, '排队类型错误');
            return true;
        }
    }

    /**
     * 检验患者药品IDs
     * @param $attribute
     * @return bool
     */
    public function checkSurplusDrugId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $surplusDrugIds = $this->getSurplusDrugId();
        if (empty($surplusDrugIds)) {
            $this->addError($attribute, '患者药品参数不能为空');
            return true;
        }

        $this->_patientDrugSurplusList = $drugSurplusList = DrugSurplus::find()->alias('ds')
            ->select([
                'ds.*',
                'dc.drug_type',
            ])
            ->innerJoin(DrugConfig::tableName().' dc', 'dc.id = ds.drug_config_id')
            ->where(['ds.id' => $surplusDrugIds])
            ->asArray()
            ->all();
        if (count($drugSurplusList) != count($surplusDrugIds)) {
            $this->addError($attribute, '患者药品参数错误');
            return true;
        }

        foreach ($drugSurplusList as $drugSurplus) {
            if ($drugSurplus['patient_user_id'] != $this->patient_user_id) {
                $this->addError($attribute, '非该患者药品');
                return true;
            }
            if ($drugSurplus['status'] != DrugSurplus::STATUS_ENABLE) {
                $this->addError($attribute, '患者药品已删除');
                return true;
            }
            if ($drugSurplus['surplus_num'] <= 0) {
                $this->addError($attribute, '患者药品次数不足');
                return true;
            }
            if ($drugSurplus['drug_type'] != $this->type) {
                $this->addError($attribute, '患者药品类型错误');
                return true;
            }
        }
    }

    /**
     * 检验操作人ID
     * @param $attribute
     * @return bool
     */
    public function checkOperateId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $member = Member::findOne($this->operate_id);
        if (empty($member)) {
            $this->addError($attribute, '操作人不存在');
            return true;
        }
        $exist = Attr::find()->alias('ma')
            ->innerJoin(Department::tableName().' d', 'd.id = ma.department_id')
            ->where([
                'ma.member_id' => $this->operate_id,
                'd.name' => Department::NAME_INFUSION,
                'd.status' => Department::STATUS_ENABLE,
            ])
            ->one();
        if (empty($exist)) {
            $this->addError($attribute, '操作人非输液部门');
            return true;
        }
    }

    /**
     * 获取患者信息
     * @return User|null
     */
    public function getPatientInfo(): ?User
    {
        if (is_null($this->_patientInfo)) {
            $this->_patientInfo = User::findOne($this->patient_user_id);
        }

        return $this->_patientInfo;
    }

    /**
     * 获取队列信息
     * @return InfusionQueue|null
     */
    public function getQueueInfo(): ?InfusionQueue
    {
        if (is_null($this->_queueInfo)) {
            $this->_queueInfo = InfusionQueue::findOne($this->id);
        }

        return $this->_queueInfo;
    }

    /**
     * 获取药品配置IDs
     * @return array
     */
    public function getSurplusDrugId(): array
    {
        if (!is_array($this->surplus_drug_id)) {
            $this->surplus_drug_id = explode(',', $this->surplus_drug_id);
        }

        return array_filter($this->surplus_drug_id);
    }

    /**
     * 获取患者未完成队列
     * @return InfusionQueue|null
     */
    public function getOldQueueInfo(): ?InfusionQueue
    {
        if (is_null($this->_oldQueueInfo)) {
            $today = DateHelper::today();
            
            /**
             * @var $data InfusionQueue|null
             */
            $data = InfusionQueue::find()
                ->where([
                    'project_id' => $this->project_id,
                    'patient_user_id' => $this->patient_user_id,
                    'type' => $this->type,
                    'status' => [InfusionQueue::STATUS_WAIT, InfusionQueue::STATUS_CALLING]
                ])
                ->andWhere(['>=', 'created_at', $today['start']])
                ->andWhere(['<=', 'created_at', $today['end']])
                ->one();
            $this->_oldQueueInfo = $data;
        }

        return $this->_oldQueueInfo;
    }

    /**
     * 患者药品信息
     * @return array
     */
    public function getPatientDrugSurplusList(): array
    {
        return $this->_patientDrugSurplusList;
    }

    /**
     * 患者药品配置IDs
     * @return int[]
     */
    public function getDrugConfigIds(): array
    {
        $ids = array_column($this->_patientDrugSurplusList, 'drug_config_id');
        $idsFormat = [];
        foreach ($ids as $id) {
            $idsFormat[] = (int)$id;
        }
        sort($idsFormat);
        return $idsFormat;
    }

    /**
     * 最大号码
     * @return int
     */
    public function getMaxOrderNum(): int
    {
        if (is_null($this->_maxOrderNum)) {
            $today = DateHelper::today();

            $this->_maxOrderNum = InfusionQueue::find()
                ->where([
                    'project_id' => $this->project_id,
                    'type' => $this->type,
                ])
                ->andWhere(['>=', 'created_at', $today['start']])
                ->andWhere(['<=', 'created_at', $today['end']])
                ->max('order_num') ?: 0;
        }

        return $this->_maxOrderNum;
    }

    /**
     * 队列患者药品IDs
     * @return InfusionQueueDrug[]
     */
    public function getQueueDrugSurplusList(): array
    {
        if (is_null($this->_queueDrugSurplusList)) {
            $this->_queueDrugSurplusList = InfusionQueueDrug::find()
                ->where([
                    'queue_id' => $this->id,
                ])
                ->all();
        }

        return $this->_queueDrugSurplusList;
    }
}
